﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEngine;

/// <summary>
/// ECS世界基类
/// </summary>
public class ECSWorldBase
{
    public delegate void EntityChangeCallBack(ECSEntityBase entity);
    #region field
    /// <summary>
    /// 世界名字
    /// </summary>
    public string name;

    #region SyncLevel enum
    /// <summary>
    /// 同步规则
    /// </summary>
    public enum SyncLevel
    {
        status,
        Fame
    }


    #endregion

    private SyncLevel m_syncLevel;//同步规则
    public SyncLevel Synclevel
    {
        get { return m_syncLevel; }
        set { m_syncLevel = value; }
    }
    /// <summary>
    /// 世界是否运行
    /// </summary>
    public bool IsStart { get; set; }
    /// <summary>
    /// 世界是否结束
    /// </summary>
    public bool IsFinish { get; set; }
    /// <summary>
    /// 是否是客户端
    /// </summary>
    public bool IsClient { get; set; } = true;
    /// <summary>
    /// 是否在本地运行（非联网）
    /// </summary>
    public bool IsLocal { get; set; } = false;
    /// <summary>
    /// 是否是插值帧
    /// </summary>
    public bool IsInterFrame { get; set; } = false;
    /// <summary>
    /// 运行到第几帧
    /// </summary>
    public int FrameCount { get; set; }
    /// <summary>
    /// 组件数目，区分组件哈希下标
    /// </summary>
    public ECSCompoentTypeBase compoentType { get; set; }


    #endregion

    #region 系统，实体，单例组件
    /// <summary>
    /// ECS组管理器
    /// </summary>
    public ECSGroupMgr group = null;
    /// <summary>
    /// 世界中所有系统
    /// </summary>
    public List<ECSSystemtBase> m_systemList = new List<ECSSystemtBase>();
    /// <summary>
    /// 世界所有实体字典
    /// </summary>
    public Dictionary<int, ECSEntityBase> m_entityDic = new Dictionary<int, ECSEntityBase>();
    /// <summary>
    /// 世界所有实体列表
    /// </summary>
    public List<ECSEntityBase> m_entityList = new List<ECSEntityBase>();
    /// <summary>
    /// 世界所有单例组件字典
    /// </summary>
    public Dictionary<string, SingletonCompoent> m_singletonComDic = new Dictionary<string, SingletonCompoent>();
    #endregion

    #region Record_Revert RecordSystem集合
    private bool m_isCertainty;
    public bool IsCertainty//是否运行的数据都是确定的（本地/服务器）
    {
        get
        {
            if (IsLocal || !IsClient)
            {
                return true;
            }
            else
            {
                return m_isCertainty;
            }
        }
        set { m_isCertainty = value; }
    }
    /// <summary>
    /// 是否推倒重计算
    /// </summary>
    public bool IsRecalc { get; set; }
    /// <summary>
    /// 世界所有的记录系统（片刻组件copy数据，普通组件拷贝引用）
    /// </summary>
    public List<ECSRecordSystemBase> recordList = new List<ECSRecordSystemBase>();
    /// <summary>
    /// 世界所有的记录系统字典<类型名，对应系统>（片刻组件copy数据，普通组件拷贝引用）
    /// </summary>
    public Dictionary<string, ECSRecordSystemBase> recordDic = new Dictionary<string, ECSRecordSystemBase>();
    #endregion

    #region Event ecs事件类，实体以及组件更改事件
    /// <summary>
    /// ECS事件
    /// </summary>
    public ECSEvent eventSystem = null;//事件字典，派发事件缓存
    /// <summary>
    /// ecs实体创建事件
    /// </summary>
    public event EntityChangeCallBack OnEntityCreate;
    public event EntityChangeCallBack OnEntityOptimizeCreate;
    /// <summary>
    /// ecs实体销毁事件
    /// </summary>
    public event EntityChangeCallBack OnEntityDestory;
    public event EntityChangeCallBack OnEntityOptimizeDestory;
    /// <summary>
    /// ecs实体将销毁事件
    /// </summary>
    public event EntityChangeCallBack OnEntityWillBeDestory;
    public event EntityChangeCallBack OnEntityOptimizeWillBeDestory;
    /// <summary>
    /// ecs实体组件添加事件
    /// </summary>
    public event EntityCompoentChangeCallBack OnEntityCoompAdd;
    /// <summary>
    /// 实体组件移除回调
    /// </summary>
    public event EntityCompoentChangeCallBack OnEntityCoompRemove;
    /// <summary>
    /// 实体组件改变回调
    /// </summary>
    public event EntityCompoentReplaceCallBack OnEntityCoompChange;

    #endregion

    #region Oninit
    public virtual void OnInit(bool Client)
    {
        eventSystem = new ECSEvent(this);//初始化ecs事件
        compoentType = GetComponentType();//反射创建组件类型对象
        //组件池
        this.IsClient = Client;//客户端运行
        try
        {
            InitSystem();//初始化添加系统
            if (IsClient)
            {
                InitRecordSystem();//初始化回滚系统
            }
            InitGroup();
            GameStart();
        }
        catch (Exception e)
        {
            Debug.LogError("世界初始化失败:" + name + e.ToString());
        }
    }


    #endregion

    #region 反射创建ECSCompoentTypeBase对象
    /// <summary>
    /// 反射创建组件类型类
    /// </summary>
    /// <returns></returns>
    private ECSCompoentTypeBase GetComponentType()
    {
        Type t = typeof(ECSCompoentTypeBase);
        Assembly assem = t.Assembly;
        foreach (Type item in assem.GetTypes())
        {
            if (item.BaseType == t)
            {
                return (ECSCompoentTypeBase)Activator.CreateInstance(item);
            }
        }

        return (ECSCompoentTypeBase)Activator.CreateInstance(t);
    }


    #endregion

    #region get世界中所有的系统，以此来反射创建 vitual GetSystemType/GetRecordType/GetRecordSingletonTypes
    /// <summary>
    /// 获取世界中所有的系统类型，以此来反射创建
    /// </summary>
    /// <returns></returns>
    public virtual Type[] GetSystemType()
    {
        return new Type[0];
    }
    //获取所有需要record的组件
    public virtual Type[] GetRecordType()
    {
        return new Type[0];
    }
    /// <summary>
    /// 获取世界中所有耀魂滚得单例类型，以此来反射创建对象
    /// </summary>
    /// <returns></returns>
    public virtual Type[] GetRecordSingletonTypes()
    {
        return new Type[0];
    }


    #endregion

    #region 初始化系统，记录系统，单例记录系统，组管理器《组管理器中的组件改变事件置入世界的组件改变事件》

    /// <summary>
    /// 初始化系统
    /// </summary>
    private void InitSystem()
    {
        Type[] types = GetSystemType();//获取所有系统
        foreach (var item in types)
        {
            if (item.BaseType != typeof(ECSSystemtBase))
            {
                Debug.LogError("初始化系统失败，类型:" + item.FullName + "不是系统类");
            }
            else
            {
                ECSSystemtBase sys = (ECSSystemtBase)item.Assembly.CreateInstance(item.FullName);
                m_systemList.Add(sys);
                sys.MyWorld = this;
                sys.OnInit();
            }
        }
    }
    /// <summary>
    /// 初始化记录系统（普通记录系统，记录单例系统）
    /// </summary>
    private void InitRecordSystem()
    {
        Type[] types = GetSystemType();
        foreach (var item in types)
        {
            //如果组件类派生自片刻组件
            if (item.IsSubclassOf(typeof(ECSMomentCompoentBase)))
            {
                Type type = typeof(EcsRecordSystem<>);
                type = type.MakeGenericType(item);

                ECSRecordSystemBase rc = (ECSRecordSystemBase)Activator.CreateInstance(type);
                recordList.Add(rc);//添加进记录系统列表
                recordDic.Add(rc.Name, rc);//添加进记录系统字典
                rc.MyWorld = this;
                rc.OnInit();
            }
            else
            {
                Debug.LogError("记录系统过滤中的组件类型有误，应书写为继承于片刻组件的类型，此处为" + item.FullName);
            }
        }
        types = GetRecordSingletonTypes();//获取要回滚的单例组件
        foreach (var item in types)
        {
            //如果组件类派生自片刻组件
            if (item.IsSubclassOf(typeof(ECSSingletonMomentCompoentBase)))
            {
                Type type = typeof(EcsRecordSingletonSystem<>);
                type = type.MakeGenericType(item);

                ECSRecordSystemBase rc = (ECSRecordSystemBase)Activator.CreateInstance(type);
                recordList.Add(rc);//添加进记录系统列表
                recordDic.Add(rc.Name, rc);//添加进记录系统字典
                rc.MyWorld = this;
                rc.OnInit();
            }
            else
            {
                Debug.LogError("记录系统过滤中的组件类型有误，应书写为继承于单例片刻组件的类型，此处为" + item.FullName);
            }
        }
    }
    /// <summary>
    /// 初始化组，将组中的组件改变事件置入世界的组件改变事件中
    /// </summary>
    private void InitGroup()
    {
        @group = new ECSGroupMgr(this);
        OnEntityCoompAdd += @group.OnEntityComponentChange;
        OnEntityCoompRemove += @group.OnEntityComponentChange;

    }

    #endregion

    #region GameStart 执行所有系统的Start方法

    private void GameStart()
    {
        for (int i = 0,j=m_systemList.Count; i < j; i++)
        {
            m_systemList[i].OnGameStar();
        }
    }


    #endregion

    #region Dispose___未完善

    public void Dispose()
    {
        Debug.Log("world dispose " + m_entityList.Count);
        while (m_entityList.Count>0)
        {
            DestoryEntityAndDispatch(m_entityList[0]);
        }

        for (int i = 0; i < destoryCache.Count; i++)
        {
            DispatchEntityWillBeDestory(destoryCache[i]);
            DispatchOptimizeDestory(destoryCache[i]);
        }
        destoryCache.Clear();
        m_entityList.Clear();
        m_entityDic.Clear();
        for (int i = 0; i < m_systemList.Count; i++)
        {
            m_systemList[i].OnDispose();
        }
        m_systemList.Clear();
        recordList.Clear();
        recordDic.Clear();
    }


    #endregion

    #region Update

    private int SysCount;
    private void GoUP(int deltaTime)
    {
        SysCount = m_systemList.Count;
        BeforeUpdate(deltaTime,SysCount);
        Update(deltaTime,SysCount);
        LateUpdate(deltaTime,SysCount);
    }
    /// <summary>
    /// 调用所有系统的beforeupdate
    /// </summary>
    /// <param name="deltaTime"></param>
    private void BeforeUpdate(int deltaTime,int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].BeforeUpdate(deltaTime);
        }
    }

    private void Update(int deltaTime, int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].Update(deltaTime);
        }
    }
    private void LateUpdate(int deltaTime, int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].LateUpdate(deltaTime);
        }
    }

    #endregion

    #region FixedUpdate

    private void GoFixedUp(int deltaTime)
    {
        SysCount = m_systemList.Count;
        BeforeFixedUpdat(deltaTime,SysCount);
        FixedUpdat(deltaTime,SysCount);
        LateFixedUpdat(deltaTime,SysCount);
    }
    private void BeforeFixedUpdat(int deltaTime,int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].BeforeFixedUpdate(deltaTime);
        }
    }
    private void FixedUpdat(int deltaTime, int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].FixedUpdate(deltaTime);
        }
    }
    private void LateFixedUpdat(int deltaTime, int count)
    {
        for (int i = 0; i < count; i++)
        {
            m_systemList[i].LateFixedUpdate(deltaTime);
        }
    }
    #endregion

    #region EndFrame
    private void EndFrame(int deltaTime)
    {
        for (int i = 0,j=m_systemList.Count; i < j; i++)
        {
            m_systemList[i].EndFrame(deltaTime);
        }
    }
    #endregion

    #region CallByPause
    private void OnlyCallByPause()
    {
        for (int i = 0, j = m_systemList.Count; i < j; i++)
        {
            m_systemList[i].RunByPause();
        }
    }
    #endregion

    #region Loop 执行update,fixedUpdate
    public void Loop(int deltaTime)
    {
        if (IsStart)
        {
            SysCount = m_systemList.Count;
            BeforeUpdate(deltaTime,SysCount);
            Update(deltaTime,SysCount);
        }
    }

    #endregion

    #region FixedLoop
    public void FixedLoop(int deltaTime)
    {
        if (IsStart)
        {
#if UNITY_ANDROID
            ConnectStatusCompoent csc = GetSingletonComp<ConnectStatusCompoent>();
            //如果不是单机并且连接状态的确认帧小于等于世界帧数木-4
            if (csc.ClearFrame<=FrameCount-4&&IsLocal.Equals(false))
            {
                return;
            }
#endif
            if (IsClient)
            {
                Record(FrameCount);
            }

            FrameCount++;
            GoFixedUp(deltaTime);//固定帧循环
            LazyExcuteEntityOperation();//集中执行实体的创建删除操作
            EndFrame(deltaTime);//结束帧
        }
        else
        {
            OnlyCallByPause();//暂停时执行
        }
    }

    #endregion

    #region OptimisticFixedLoop 确定循环
    public void OptimisticFixedLoop(int deltaTime)
    {
        if (IsStart)
        {
            IsCertainty = true;//确定帧
            FrameCount++;//帧数目自增
            GoFixedUp(deltaTime);
            LazyExcuteEntityOperation();
            EndFrame(deltaTime);//集中执行实体的创建删除操作
        }
        else
        {
            OnlyCallByPause();
        }
    }

    #endregion

    #region Recalc 所有sync系统的Recalc重计算

    public void CallRecalc()
    {
        for (int i = 0,j=m_systemList.Count; i < j; i++)
        {
            m_systemList[i].Recalc();
        }
    }


    #endregion

    #region Recalc

    public void Recalc(int frame, int deltaTime)
    {
        FrameCount = frame;

        GoFixedUp(deltaTime);
                         //集中执行实体的创建删除操作
         LazyExcuteEntityOperation();//集中执行实体的创建删除操作

        EndFrame(deltaTime);
    }

    #endregion

    #region Record 所有记录系统执行记录，记录随机数

    public void Record(int frame)
    {
        if (IsLocal)
        {
            return;
        }
        //
        RandomRecord(frame);
        for (int i = 0,j=recordList.Count; i < j; i++)
        {
            recordList[i].Record(frame);
        }
    }

    #endregion

    #region RevertToFrame

    public void RevertToFrame(int frame)
    {
        RandomRevertToFrame(frame);
        EntityRevertToFrame(frame);
        for (int i = 0,j=recordList.Count; i < j; i++)
        {
            recordList[i].RevertToFrame(frame);
        }

        FrameCount = frame;
    }

    #endregion

    #region ClearRecorrdCache 清除符合条件的记录系统中的记录组件列表

    public void ClearBefore(int frame)
    {
        for (int i = 0, j = recordList.Count; i < j; i++)
        {
            recordList[i].ClearBefore(frame);
        }
    }

    public void ClearAt(int frame)
    {
        for (int i = 0, j = recordList.Count; i < j; i++)
        {
            recordList[i].ClearRecordAt(frame);
        }
    }

    public void ClearAfter(int frame)
    {
        for (int i = 0, j = recordList.Count; i < j; i++)
        {
            recordList[i].ClearAfter(frame);
        }
    }

    public void ClearAll()
    {
        for (int i = 0,j=recordList.Count; i < j; i++)
        {
            recordList[i].ClearAll();
        }
    }

    #endregion

    #region GetRecordSystemBase获得某个记录系统

    /// <summary>
    /// 获得某个记录系统
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public ECSRecordSystemBase GetRecordSystemBase(string name)
    {
        if (GetExistRecordSystem(name))
        {
            return recordDic[name];
        }
        else
        {
            throw new Exception("世界无此记录系统:"+name);
        }
    }


    #endregion

    #region GetExistRecordSystem判断世界是否含有某个记录系统
    /// <summary>
    /// 判断世界是否含有某个记录系统
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public bool GetExistRecordSystem(string name)
    {
        return recordDic.ContainsKey(name);
    }

    #endregion

    #region 记录预测时的实体创建

    private void RecordEntityCreate(ECSEntityBase entity)
    {
        if (!IsClient)
        {
            return;
        }

        if (IsCertainty)
        {
            return;
        }
        //如果此帧有这个ID的创建记录，把它抵消掉
        ECSEntityRecordCompoent erc = GetSingletonComp<ECSEntityRecordCompoent>();
        if (erc.GetRecordIsExist(entity.DestoryFrame, entity.ID, EntityChangeType.Destory))
        {
            EntityRecordInfo record = erc.GetRecord(entity.DestoryFrame, entity.ID, EntityChangeType.Destory);
            erc.InfoList.Remove(record);
        }
        else
        {
            EntityRecordInfo info = new EntityRecordInfo();
            info.changeType = EntityChangeType.Create;
            info.id = entity.ID;
            info.frame = entity.CreateFrame;
            info.SaveComp(entity);
            erc.InfoList.Add(info);
        }
    }

    #endregion

    #region 记录预测时实体摧毁

    private void RecordEntityDestory(ECSEntityBase entity)
    {
        if (!IsClient)
        {
            return;
        }

        if (IsCertainty)
        {
            return;
        }
        //如果此帧有这个ID的创建记录，把它抵消掉
        ECSEntityRecordCompoent erc = GetSingletonComp<ECSEntityRecordCompoent>();
        if (erc.GetRecordIsExist(entity.DestoryFrame,entity.ID,EntityChangeType.Create))
        {
            EntityRecordInfo record = erc.GetRecord(entity.DestoryFrame, entity.ID, EntityChangeType.Create);
            erc.InfoList.Remove(record);
        }
        else
        {
            EntityRecordInfo info=new EntityRecordInfo();
            info.changeType = EntityChangeType.Destory;
            info.id = entity.ID;
            info.frame = entity.DestoryFrame;
            info.SaveComp(entity);
            erc.InfoList.Add(info);
        }
    }

    #endregion

    #region 实体还原到帧
    //逐帧倒放
    private void EntityRevertToFrame(int frame)
    {
        for (int i = FrameCount; i >=frame+1; i--)
        {
            EntityRevertOneFrame(i);
        }
    }
    //逐帧倒放
    private void EntityRevertDestoryToFrame(int frame)
    {
        for (int i = FrameCount; i >=frame+1; i--)
        {
            EntityRevertDestoryOneFrame(i);
        }
    }

    private void EntityRevertOneFrame(int frame)
    {
        ECSEntityRecordCompoent rec = GetSingletonComp<ECSEntityRecordCompoent>();
        EntityRecordInfo thisInfo;
        for (int i = 0, j = rec.InfoList.Count; i < j; i++)
        {
            thisInfo = rec.InfoList[i];
            if (thisInfo.frame.Equals(frame) )
            {
                EntityRevertOneFrame(thisInfo);
            }
            rec.InfoList.RemoveAt(i);
            i--;
            j--;
        }
    }

    private void EntityRevertDestoryOneFrame(int frame)
    {
        ECSEntityRecordCompoent rec = GetSingletonComp<ECSEntityRecordCompoent>();
        EntityRecordInfo thisInfo;
        for (int i = 0,j=rec.InfoList.Count; i < j; i++)
        {
            thisInfo = rec.InfoList[i];
            if (thisInfo.frame.Equals(frame)&&thisInfo.changeType.Equals(EntityChangeType.Destory))
            {
                EntityRevertOneFrame(thisInfo);
            }
            rec.InfoList.RemoveAt(i);
            i--;
            j--;
        }
    }

    private void EntityRevertOneFrame(EntityRecordInfo data)
    {
        if (data.changeType==EntityChangeType.Create)
        {
            RollBackCreateEntity(data.id,data.frame);
        }
        else
        {
            RollBackDestoryEntity(data.id, data.frame, data.ComList.ToArray());
        }
    }
    /// <summary>
    /// 回滚创建的实体
    /// </summary>
    /// <param name="ID"></param>
    /// <param name="frame"></param>
    private void RollBackCreateEntity(int ID, int frame)
    {
        ECSEntityBase entity = GetEntity(ID);
        entity.DestoryFrame = frame;
        DestoryEntityNoDispatch(entity);
        AddDestoryCache(entity);
    }

    /// <summary>
    /// 回滚摧毁的实体，不派发事件，并将回滚对象存入缓存
    /// </summary>
    /// <param name="ID"></param>
    /// <param name="compList"></param>
    /// <returns></returns>
    private ECSEntityBase RollBackDestoryEntity(int ID, int frame, params ECSCompoentBase[] compList)
    {
        ECSEntityBase entity = NewEntity("RollBackDestoryEntity", ID, compList);
        entity.CreateFrame = frame;
        CreateEntityNoDispatch(entity);
        AddCreateCache(entity);
        return entity;
    }
    #endregion

    #region 组件回滚



    #endregion

    #region 集中执行实体的删除操作
    private List<ECSEntityBase> destoryCache=new List<ECSEntityBase>();
    /// <summary>
    /// 集中执行实体的删除操作
    /// </summary>
    public void LazyExcuteEntityOperation()
    {
        for (int i = 0,j=destoryCache.Count; i < j; i++)
        {
            RemoveEntity(destoryCache[i]);
        }
        destoryCache.Clear();
    }


    #endregion

    #region 实体创建(recalc状态下添加实体，不进行实体创建记录)

    public ECSEntityBase CreateEntity(string identifier, params ECSCompoentBase[] comps)
    {
        identifier = FrameCount + identifier;
        int ID = identifier.ToHash();
        ECSEntityBase entity = CreateEntity(identifier, ID, comps);

        return entity;
    }

    public ECSEntityBase CreateEntity(string name, int ID, params ECSCompoentBase[] comps)
    {
        if (m_entityDic.ContainsKey(ID))
        {
            throw new Exception("创建实体失败，此标识id：" + ID + "已存在");
        }

        EcsSyncDebugSystem.AddDebugMsg("Creare" + ID + name);
        //debug记录实体创建

        ECSEntityBase entity = NewEntity(name, ID, comps);
        AddEntity(entity);
        return entity;
    }

    /// <summary>
    /// 立即创建一个实体，不要在游戏逻辑中使用
    /// </summary>
    public ECSEntityBase CreateEntityNow(string identifier, params ECSCompoentBase[] comps)
    {
        identifier = FrameCount + identifier;
        int id = identifier.ToHash();
        if (m_entityDic.ContainsKey(id))
        {
            throw new Exception("创建实体失败，此标识id："+id+"已存在");
        }
        ECSEntityBase entity= NewEntity(identifier,id,comps);
        CreateEntityAndDispatch(entity);
        return entity;
    }
    /// <summary>
    /// 新建实体（优先从销毁缓存中拉取该id实体，若里面无此id实体，进行实例化）
    /// </summary>
    /// <param name="name"></param>
    /// <param name="ID"></param>
    /// <param name="compList"></param>
    /// <returns></returns>
    private ECSEntityBase NewEntity(string name, int ID, params ECSCompoentBase[] compList)
    {
        ECSEntityBase entity;
        if (GetIsExistDispatchDestoryCache(ID))
        {
            entity = GetDispatchDestoryCache(ID);
            CopyValue(compList,entity);
        }
        else
        {
            entity=new ECSEntityBase(this);
            entity.ID = ID;
            entity.Name = name;
            entity.CreateFrame = FrameCount;

            if (compList !=null)
            {
                for (int i = 0,j=compList.Length; i < j; i++)
                {
                    if (compList[i] !=null)
                    {
                        entity.AddComp(compList[i].GetType().Name, compList[i]);
                    }
                    else
                    {
                        Debug.LogError("新建实体添加组件失败，该组件标识位空");
                    }
                    
                }
            }
        }

        return entity;
    }

    private void AddEntity(ECSEntityBase entity)
    {
        if (IsRecalc)
        {
            RecalcCreateEntity(entity);
        }
        else
        {
            CreateEntityAndDispatch(entity);
            RecordEntityCreate(entity);
        }
    }

    private void CreateEntityAndDispatch(ECSEntityBase entity)
    {
        CreateEntityNoDispatch(entity);
    }

    private void CreateEntityNoDispatch(ECSEntityBase entity)
    {
        if (m_entityDic.ContainsKey(entity.ID))
        {
            Debug.Log("创建实体冲突，该实体id"+entity.ID+"已存在");
            throw new Exception("创建实体冲突，该实体id" + entity.ID + "已存在");
        }
        m_entityDic.Add(entity.ID,entity);
        m_entityList.Add(entity);

        entity.OnCompoentAdd += DispatchEntityCompAdd;
        entity.OnCompoentRemove += DispatchEntityCompRemove;
        entity.OnCompoentReplace += DispatchEntityCompChange;

        @group.OnEntityCreate(entity);
        DispatchCreate(entity);
    }
    #endregion
    //ClientDestoryEntity(int ID)
    // DestoryEntity(int ID)
    // RemoveEntity(ECSEntityBase entity)
    //DestoryEntityAndDispatch(ECSEntityBase entity)
    //DestoryEntityNoDispatch(ECSEntityBase entity)
    // DestoryEntityNow(int id)
    #region 实体摧毁

    public void ClientDestoryEntity(int ID)
    {
        DestoryEntity(ID);
    }

    public void DestoryEntity(int ID)
    {
        if (m_entityDic.ContainsKey(ID))
        {
            ECSEntityBase entity = m_entityDic[ID];
            entity.DestoryFrame = FrameCount;
            if (!destoryCache.Contains(entity))
            {
               destoryCache.Add(entity);
               //下面存疑
                //AddDestoryCache(entity);
            }
        }
        else
        {
            Debug.LogError("无法重复销毁,id:"+ID);
        }
    }

    private void RemoveEntity(ECSEntityBase entity)
    {
        if (IsRecalc)
        {
            RecalcDestoryEntity(entity);
        }
        else
        {
            DestoryEntityAndDispatch(entity);
            RecordEntityDestory(entity);
        }
    }
    //销毁实体（从实体列表中移除）,派发事件，将实体的组件改变事件-=世界的实体改变事件
    private void DestoryEntityAndDispatch(ECSEntityBase entity)
    {
        DispatchEntityWillBeDestory(entity);
        //销毁实体（从实体列表中移除）,派发事件，将实体的组件改变事件-=世界的实体改变事件
        DestoryEntityNoDispatch(entity);
        DispatchOptimizeDestory(entity);

    }
    //销毁实体（从实体列表中移除）,派发事件，将实体的组件改变事件-=世界的实体改变事件
    private void DestoryEntityNoDispatch(ECSEntityBase entity)
    {
        //派发实体将销毁事件
        DispatchEntityWillBeDestory(entity);

        m_entityList.Remove(entity);
        m_entityDic.Remove(entity.ID);
        @group.OnEntityDestory(entity);

        DispatchEntityDestory(entity);
        //将实体中组件改变事件移除
        entity.OnCompoentAdd -= DispatchEntityCompAdd;
        entity.OnCompoentRemove -= DispatchEntityCompRemove;
        entity.OnCompoentReplace -= DispatchEntityCompChange;
    }

    public void DestoryEntityNow(int id)
    {
        ECSEntityBase entity = GetEntity(id);
        DestoryEntityAndDispatch(entity);
    }
    #endregion
    //GetEntityID(string identiflier)
    //GetEntityIsExist(int iD)  是否带有指定下标的实体
    //GetEntity(int thisId)        返回指定下标的实体
    //GetEntityList(string[] compNames) 返回世界中带有这组组件的实体
    //GetAllExistComp(string[] compNames, ECSEntityBase entity) 该实体是否包含这一组组件
    #region 获取实体______

    /// <summary>
    /// 获取标识符(当前帧数+标识符  转hash) __________________
    /// </summary>
    /// <param name="identiflier"></param>
    /// <returns></returns>
    public int GetEntityID(string identiflier)
    {
        identiflier = FrameCount + identiflier;
      
    }
    //是否带有指定下标的实体
    public bool GetEntityIsExist(int iD)
    {
        return m_entityDic.ContainsKey(iD);
    }
    //返回指定下标的实体
    public ECSEntityBase GetEntity(int thisId)
    {
        ECSEntityBase ee;
        try
        {
            if (m_entityDic.TryGetValue(thisId, out ee))
             {
                 return ee;
             }
            throw new Exception("获取实体失败GetEntity，该id：" + thisId + "下标无实体");
        }
        catch (Exception e)
        {
            throw new Exception("获取实体失败GetEntity，该id：" + thisId + "下标无实体");
        }
    }
    //返回世界中带有这组组件的实体
    public List<ECSEntityBase> GetEntityList(string[] compNames)
    {
        List<ECSEntityBase> thisList=new List<ECSEntityBase>();
        for (int i = 0,j=m_entityList.Count; i < j; i++)
        {
            if (GetAllExistComp(compNames,m_entityList[i]))
            {
                thisList.Add(m_entityList[i]);
            }
        }

        return thisList;
    }
    //该实体是否包含这一组组件
    public bool GetAllExistComp(string[] compNames, ECSEntityBase entity)
    {
        for (int i = 0, j = m_entityList.Count; i < j; i++)
        {
            if (!entity.GetExistCom(compNames[i]))
            {
                return false;
            }
        }

        return true;
    }
    #endregion
    //List<ECSEntityBase> dispatchDestoryCache已销毁实体列表
    //List<ECSEntityBase> dispatchCreateCache已创建实体列表
    //AddCreateCache(ECSEntityBase entity)
    //AddDestoryCache(ECSEntityBase entity)
    //EndRecalc() //重计算结束，集体  派发实体创建销毁回调
    //RecalcCreateEntity(ECSEntityBase entity)  //重计算创建的实体
    //RecalcDestoryEntity(ECSEntityBase entity) //重计算销毁的实体
    //CopyValue(ECSCompoentBase[] from, ECSEntityBase to) //为实体尝试更换一组 片刻组件
    //GetDispatchDestoryCache(int thisId) //从销毁缓存中尝试获取指定id的实体（thisid==entity.id）
    //GetIsExistDispatchDestoryCache(int thisId)
    //GetDispatchCreateCache(int thisId) //从创建缓存中尝试获取指定id的实体（thisid==entity.id）
    //GetIsExistDispatchCreateCache(int thisId)
    #region 回滚相关 (创建/销毁  实体键入列表中)
    /// <summary>
    /// 已销毁实体列表
    /// </summary>
    List<ECSEntityBase> dispatchDestoryCache=new List<ECSEntityBase>();
    /// <summary>
    /// 已创建实体列表
    /// </summary>
    List<ECSEntityBase> dispatchCreateCache = new List<ECSEntityBase>();

    private void AddCreateCache(ECSEntityBase entity)
    {
        if (dispatchCreateCache.Contains(entity))
        {
            Debug.LogError("此实体已存在创建缓存"+entity.ID);
            return;
        }

        if (dispatchDestoryCache.Contains(entity))
        {
            dispatchDestoryCache.Remove(entity);
            //**下面添加存疑
            dispatchCreateCache.Add(entity);
        }
        else
        {
            dispatchCreateCache.Add(entity);
        }
    }

    private void AddDestoryCache(ECSEntityBase entity)
    {
        if (dispatchDestoryCache.Contains(entity))
        {
            Debug.LogError("此实体已存在销毁缓存" + entity.ID);
            return;
        }

        if (dispatchCreateCache.Contains(entity))
        {
            dispatchCreateCache.Remove(entity);
            //**下面添加存疑
            dispatchDestoryCache.Add(entity);
        }
        else
        {
            dispatchDestoryCache.Add(entity);
        }
    }
    //重计算结束，集体  派发实体创建销毁回调
    public void EndRecalc()
    {
        for (int i = 0,j= dispatchDestoryCache.Count; i < j; i++)
        {
            DispatchEntityWillBeDestory(dispatchDestoryCache[i]);
            //DispatchEntityDestory(dispatchDestoryCache[i]);
            DispatchOptimizeDestory(dispatchDestoryCache[i]);
        }
        dispatchDestoryCache.Clear();
        for (int i = 0,j=dispatchCreateCache.Count; i < j; i++)
        {
            //DispatchCreate(dispatchCreateCache[i]);
            DispatchOptimizeCreate(dispatchCreateCache[i]);
        }
        dispatchCreateCache.Clear();
    }
    //重计算创建的实体
    private void RecalcCreateEntity(ECSEntityBase entity)
    {
        AddCreateCache(entity);
        CreateEntityNoDispatch(entity);
        RecordEntityCreate(entity);
    }
    //重计算销毁的实体
    private void RecalcDestoryEntity(ECSEntityBase entity)
    {
        AddDestoryCache(entity);
        DestoryEntityNoDispatch(entity);
        RecordEntityDestory(entity);
    }
    //为实体长手更换一组 片刻组件
    private void CopyValue(ECSCompoentBase[] from, ECSEntityBase to)
    {
        for (int i = 0,j=from.Length; i < j; i++)
        {
            if (from[i] is ECSMomentCompoentBase)
            {
                ECSMomentCompoentBase mc = (ECSMomentCompoentBase) from[i];
                to.ChangeCom(mc.GetType().ToString(),mc);
            }
        }
    }
    //从销毁缓存中尝试获取指定id的实体（thisid==entity.id）
    public ECSEntityBase GetDispatchDestoryCache(int thisId)
    {
        for (int i = 0,j=dispatchDestoryCache.Count; i < j; i++)
        {
            if (dispatchDestoryCache[i].ID==thisId)
            {
                return dispatchDestoryCache[i];
            }
        }
        throw new Exception("GetDispatchDestoryCache失败,dispatchDestoryCache中不存在该id：" + thisId+"的实体");
    }
    //销毁缓存中是否存在指定id的实体（thisid==entity.id）
    public bool GetIsExistDispatchDestoryCache(int thisId)
    {
        for (int i = 0, j = dispatchDestoryCache.Count; i < j; i++)
        {
            if (dispatchDestoryCache[i].ID == thisId)
            {
                return true;
            }
        }

        return false;
    }
    //从创建缓存中尝试获取指定id的实体（thisid==entity.id）
    public ECSEntityBase GetDispatchCreateCache(int thisId)
    {
        for (int i = 0, j = dispatchCreateCache.Count; i < j; i++)
        {
            if (dispatchCreateCache[i].ID == thisId)
            {
                return dispatchCreateCache[i];
            }
        }
        throw new Exception("GetDispatchCreateCache失败,dispatchCreateCache中不存在该id：" + thisId + "的实体");
    }
    //创建缓存中是否存在指定id的实体（thisid==entity.id）
    public bool GetIsExistDispatchCreateCache(int thisId)
    {
        for (int i = 0, j = dispatchCreateCache.Count; i < j; i++)
        {
            if (dispatchCreateCache[i].ID == thisId)
            {
                return true;
            }
        }

        return false;
    }
    #endregion

    //GetSingletonComp<T>()
    //GetSingletonComp(string compName)
    //ChangeSingletonComp<T>(T deepCopy)
    //ChangeSingletonComp(string compName, SingletonCompoent comp)
    #region 获取,创建，更改单例组件
    /// <summary>
    /// 获取单例组件，若不存在则实例化并添加入字典中
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T GetSingletonComp<T>()where T:SingletonCompoent,new()
    {
        Type thisType = typeof(T);
        string key = thisType.Name;
        if (thisType.IsGenericType)
        {
            //使用Type.GetGenericArguments()获取泛型参数集合 在这里, 集合中的第一个元素等价于typeof(ClassA)
            key += thisType.GetGenericArguments()[0].Name;
        }

        SingletonCompoent com = null;
        if (m_singletonComDic.ContainsKey(key))
        {
            com = m_singletonComDic[key];
        }
        else
        {
            try
            {
                com = new T();
                com.Init();
                com.World = this;
                m_singletonComDic.Add(key,com);
            }
            catch (Exception e)
            {
               throw new Exception("创建单例组件失败"+key+e.ToString());
            }
        }

        return (T) com;
    }

    public SingletonCompoent GetSingletonComp(string compName)
    {
        SingletonCompoent com = null;
        if (m_singletonComDic.TryGetValue(compName,out com))
        {
            return com;
        }
        else
        {
            try
            {
                Type thisType = Type.GetType(compName);
                com = (SingletonCompoent) thisType.Assembly.CreateInstance(thisType.FullName);
                com.Init();
                com.World = this;
                m_singletonComDic.Add(compName,com);
                return com;
            }
            catch (Exception e)
            {
                throw new Exception("创建单例组件失败" + compName+e.ToString());
            }
            
        }
    }
    public void ChangeSingletonComp<T>(T deepCopy) where T : SingletonCompoent, new()
    {
        string comName = typeof(T).Name;
        ChangeSingletonComp(comName, deepCopy);
    }
    //更改单例组件
    public void ChangeSingletonComp(string compName, SingletonCompoent comp)
    {
        if (m_singletonComDic.ContainsKey(compName))
        {
            // int index = compoentType.GetCompoentIndex(compName);
            m_singletonComDic[compName] = comp;
        }
        else
        {
            m_singletonComDic.Add(compName,comp);
        }

        comp.World = this;
    }
    #endregion
    //DispatchCreate(ECSEntityBase entity)
    //DispatchEntityWillBeDestory(ECSEntityBase entity)
    //DispatchEntityDestory(ECSEntityBase entity)
    //DispatchEntityCompAdd(ECSEntityBase entity, int compIndex, ECSCompoentBase comp)
    //DispatchEntityCompRemove(ECSEntityBase entity, int compIndex, ECSCompoentBase comp)
    //DispatchEntityCompChange(ECSEntityBase entity, int compIndex, ECSCompoentBase comp,ECSCompoentBase newCom)
    #region 事件派发<实体创建销毁事件派发，实体组件更改事件派发>

    private void DispatchCreate(ECSEntityBase entity)
    {
        try
        {
            if (OnEntityCreate !=null)
            {
                OnEntityCreate(entity);
            }
        }
        catch (Exception e)
        {
           Debug.LogError("实体创建回调派发失败，可能为空");
        }
    }
    private void DispatchOptimizeCreate(ECSEntityBase entity)
    {
        try
        {
            if (OnEntityOptimizeCreate != null)
            {
                OnEntityOptimizeCreate(entity);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体创建回调派发失败，可能为空");
        }
    }
    private void DispatchEntityWillBeDestory(ECSEntityBase entity)
    {
        try
        {
            if (OnEntityWillBeDestory != null)
            {
                OnEntityWillBeDestory(entity);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体即将销毁回调派发失败，可能为空");
        }
    }

    private void DispatchOptimizeDestory(ECSEntityBase entity)
    {
        try
        {
            if (OnEntityOptimizeDestory !=null)
            {
                OnEntityOptimizeDestory(entity);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("DispatchDestroy OnEntityDestroyed: " + e.ToString());
        }
    }
    private void DispatchEntityDestory(ECSEntityBase entity)
    {
        try
        {
            if (OnEntityDestory != null)
            {
                OnEntityDestory(entity);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体销毁回调派发失败，可能为空");
        }
    }

    private void DispatchEntityCompAdd(ECSEntityBase entity, int compIndex, ECSCompoentBase comp)
    {
        try
        {
            if (OnEntityCoompAdd != null)
            {
                OnEntityCoompAdd(entity,compIndex,comp);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体组件添加回调派发失败，可能为空");
        }
    }

    private void DispatchEntityCompRemove(ECSEntityBase entity, int compIndex, ECSCompoentBase comp)
    {
        try
        {
            if (OnEntityCoompRemove != null)
            {
                OnEntityCoompRemove(entity, compIndex, comp);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体组件移除回调派发失败，可能为空");
        }
    }

    private void DispatchEntityCompChange(ECSEntityBase entity, int compIndex, ECSCompoentBase comp,ECSCompoentBase newCom)
    {
        try
        {
            if (OnEntityCoompChange != null)
            {
                OnEntityCoompChange(entity, compIndex, comp,newCom);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("实体组件更改回调派发失败，可能为空");
        }
    }
    #endregion

    //GetRandom()
    //GetRandom(int min, int max)
    //RandomRevertToFrame(int frame)
    //RandomRecord(int frame)
    //Dictionary<int ,int>m_randomDic
    #region 随机数 ,如果debug系统的debug清空下，那么将随机数记录在debug系统中

    private int m_RandomSeed = 0;
    private int m_randomA = 9301;
    private int m_randomB = 49297;
    private int m_randomC = 233280;
    /// <summary>
    /// 已产生的随机数字典
    /// </summary>
    private Dictionary<int ,int>m_randomDic=new Dictionary<int, int>();
    /// <summary>
    /// 获取随机数，如果是debug，那么记录随机数
    /// </summary>
    /// <returns></returns>
    public int GetRandom()
    {
        m_RandomSeed=System.Math.Abs((m_RandomSeed*m_randomA+m_randomB)%m_randomC);
        if (EcsSyncDebugSystem.isDebug)
        {
            EcsSyncDebugSystem.RecordRandomChange(FrameCount, m_RandomSeed, "");
        }

        return m_RandomSeed;
    }

    public int GetRandom(int min, int max)
    {
        int result = GetRandom();
        result = min + result % (max - min);
        return result;
    }
    /// <summary>
    /// 随机数还原
    /// </summary>
    /// <param name="frame"></param>
    private void RandomRevertToFrame(int frame)
    {
        if (m_randomDic.ContainsKey(frame))
        {
            m_RandomSeed = m_randomDic[frame];
        }
        else
        {
            Debug.LogError("随机数回滚失败,第"+frame+"帧的随机数为空");
        }
    }
    /// <summary>
    /// 随机数记录
    /// </summary>
    /// <param name="frame"></param>
    private void RandomRecord(int frame)
    {
        if (m_randomDic.ContainsKey(frame))
        {
            m_randomDic[frame] = m_RandomSeed;
        }
        else
        {
            m_randomDic.Add(frame,m_RandomSeed);
        }
    }
    #endregion

    #region MyRegion
    //为所有实体添加记录组件
    public bool GetIsAllMsg()
    {
        List<ECSEntityBase> list = GetPlayerList();
        bool isAllMessage = true;
        for (int i = 0,j=list.Count; i < j; i++)
        {
            AddRecordComp(list[i]);//为所有实体添加记录组件
        }

        return isAllMessage;
    }

    public int GetCacheCount()
    {
        int count = 0;
        List<ECSEntityBase> list = GetPlayerList();
        bool isAllMessage = true;
        for (int i = FrameCount + 1; ; i++)
        {
            if (list.Count.Equals(0))
            {
                break;
            }

            for (int j = 0; j < list.Count; j++)
            {
                //为实体添加记录组件
                AddRecordComp(list[i]);
            }

            if (isAllMessage)
            {
                count++;
            }
            else
            {
                break;
            }
        }

        return count;
    }

    public void AddRecordComp(ECSEntityBase entity)
    {
        //if (!entity.GetExistComp(ComponentType.PlayerCommandRecordComponent))
        //{
        //    PlayerCommandRecordComponent rc = new PlayerCommandRecordComponent();

        //    //自动添加记录组件
        //    entity.AddComp(rc);
        //}
    }
    private bool isGetHashCode = false;
    private int filterNameHashCode;
    private string[] filter=new string[] { "CommandComponent", "RealPlayerComponent" };

    public List<ECSEntityBase> GetPlayerList()
    {
        if (!isGetHashCode)
        {
            isGetHashCode = true;

            filterNameHashCode = group.StringArrayToInt(filter);//得到哈希
        }
        return group.GetEntityByFilter(filterNameHashCode, filter);//从ecs组管理器中返回实体
    }
    #endregion





















}

